﻿--MacaroonXtras, a World of Warcraft® user interface addon.
--Copyright© 2008 Connor H. Chenoweth, aka Maul

Macaroon.BagBars = {}
Macaroon.BagButtons = {}
Macaroon.MenuBars = {}
Macaroon.MenuButtons = {}

MacaroonXtrasSavedState = {}

local bagElements = {}
local menuElements = {}
local addonData, sortData = {}

local currentVersion = 30000.11
local load, ss, playerEnteredWorld

local lower = string.lower
local sort = table.sort
local format = string.format

local GetAddOnInfo = _G.GetAddOnInfo
local GetAddOnMemoryUsage = _G.GetAddOnMemoryUsage
local GetAddOnCPUUsage = _G.GetAddOnCPUUsage
local GetScriptCPUUsage = _G.GetScriptCPUUsage
local UpdateAddOnMemoryUsage = _G.UpdateAddOnMemoryUsage
local UpdateAddOnCPUUsage = _G.UpdateAddOnCPUUsage

local copyTable = Macaroon.copyTable
local clearTable = Macaroon.clearTable
local getChildrenAndRegions = Macaroon.getChildrenAndRegions

local function updateButtonData(button, bar, state)

	button.bar = bar
	button.alpha = bar.config.alpha
	button.showGrid = bar.config.showGrid
	button:SetAttribute("showgrid-bar", bar.config.showGrid)
	button.config.showstates = state
	button:SetAttribute("showstates", state)

	button.skincolor = bar.config.skincolor
	button.rangecolor = bar.config.rangecolor
	button.manacolor = bar.config.manacolor
	button.buffcolor = bar.config.buffcolor
	button.debuffcolor = bar.config.debuffcolor
	button.hovercolor = bar.config.hovercolor
	button.equipcolor = bar.config.equipcolor
	button.cdcolor1 = bar.config.cdcolor1
	button.cdcolor2 = bar.config.cdcolor2
	button.bdcolor1 = bar.config.bdcolor1
	button.bdcolor2 = bar.config.bdcolor2

	button.config.bar = bar:GetID()
	button.config.stored = false

	button:SetFrameStrata(bar.config.buttonStrata)

	button:SetFrameLevel(4)

	if (bar.handler) then
		Macaroon.UpdateButtonVisibility(button, bar.handler:GetAttribute("state-current"))
	end
end

local function buttonDefaults(index, button)

	button.config = {
		bar = 0,
		barPos = 0,
		showstates = "",
		laststate = "",
		hotKeys = ":",
		hotKeyText = ":",
		hotKeyLock = false,
		scale = 1,
		XOffset = 0,
		YOffset = 0,
		mouseoverAnchor = false,
		clickAnchor = false,
		anchorDelay = "0.1",
		anchoredBar = "",
	}
end

local function createBagButton(index)

	local button

	if (_G["MacaroonBagButton"..index]) then
		button = _G["MacaroonBagButton"..index]
	else
		button = CreateFrame("CheckButton", "MacaroonBagButton"..index, UIParent, "MacaroonAnchorButtonTemplate")
	end

	local buttonName = button:GetName()
	local objects = getChildrenAndRegions(button)

	for k,v in pairs(objects) do
		local name = gsub(v, button:GetName(), "")
		button[lower(name)] = _G[v]
	end

	button:SetID(index)
	button.id = index
	button:SetWidth(bagElements[index]:GetWidth()+1)
	button:SetHeight(bagElements[index]:GetHeight()+1)
	button:SetHitRectInsets(button:GetWidth()/2, button:GetWidth()/2, button:GetHeight()/2, button:GetHeight()/2)

	button.editframe:SetPoint("TOPLEFT")
	button.editframe:SetPoint("BOTTOMRIGHT")
	button.editframetype:SetText("bag")

	buttonDefaults(index, button)
	button.bagelement = bagElements[index]

	objects = getChildrenAndRegions(button.bagelement)

	for k,v in pairs(objects) do
		local name = gsub(v, button.bagelement:GetName(), "")
		button[lower(name)] = _G[v]
	end

	button.bagelement:ClearAllPoints()
	button.bagelement:SetParent(button)
	button.bagelement:Show()
	button.bagelement:SetPoint("CENTER", button, "CENTER")
	button.bagelement:SetScale(1)
	button.bagelement:SetScript("OnClick", BagSlotButton_OnClick)

	button.updateButtonData = updateButtonData

	button:SetAttribute("showgrid", 0)
	button:SetAttribute("showstates", "")
	button:SetAttribute("hotkeys", "")
	button:SetAttribute("hasaction", true)
	button:SetAttribute("_childupdate", [[

			self:SetAttribute("stateshown", false)

			for showstate in gmatch(self:GetAttribute("showstates"), "[^;]+") do
				if (message and strfind(message, showstate)) then
					if (self:GetAttribute("hasaction") or self:GetAttribute("showgrid-bar") or self:GetAttribute("editmode")) then
						self:Show()
					end
					self:SetAttribute("stateshown", true)
				end
			end

			if (not self:GetAttribute("stateshown")) then
				self:Hide()
			end
		]] )


	if (not ss["bags"]) then
		ss["bags"] = {}
	end

	ss["bags"][index] = { button.config }

	Macaroon.BagButtons[index] = { button, 1 }

	return button
end

local function createMenuButton(index)

	local button

	if (_G["MacaroonMenuButton"..index]) then
		button = _G["MacaroonMenuButton"..index]
	else
		button = CreateFrame("CheckButton", "MacaroonMenuButton"..index, UIParent, "MacaroonAnchorButtonTemplate")
	end

	local buttonName = button:GetName()
	local objects = getChildrenAndRegions(button)

	for k,v in pairs(objects) do
		local name = gsub(v, button:GetName(), "")
		button[lower(name)] = _G[v]
	end

	button:SetID(index)
	button.id = index
	button:SetWidth(menuElements[index]:GetWidth()*0.86)
	button:SetHeight(menuElements[index]:GetHeight()/1.65)
	button:SetHitRectInsets(button:GetWidth()/2, button:GetWidth()/2, button:GetHeight()/2, button:GetHeight()/2)

	button.editframe:SetPoint("TOPLEFT", -3, 0)
	button.editframe:SetPoint("BOTTOMRIGHT", 3, 0)
	button.editframetype:SetText("menu")
	button.editframetype:SetTextHeight(8)

	buttonDefaults(index, button)
	button.menuelement = menuElements[index]

	objects = getChildrenAndRegions(button.menuelement)

	for k,v in pairs(objects) do
		local name = gsub(v, button.menuelement:GetName(), "")
		button[lower(name)] = _G[v]
	end

	button.menuelement.normaltexture = button.menuelement:CreateTexture("$parentNormalTexture", "OVERLAY", "MacaroonCheckButtonTextureTemplate")
	button.menuelement.normaltexture:ClearAllPoints()
	button.menuelement.normaltexture:SetPoint("CENTER", 0, 0)
	button.menuelement.icontexture = button.menuelement:GetNormalTexture()
	button.menuelement:ClearAllPoints()
	button.menuelement:SetParent(button)
	button.menuelement:Show()
	button.menuelement:SetPoint("BOTTOM", button, "BOTTOM", 0, -1)
	button.menuelement:SetHitRectInsets(3, 3, 23, 3)

	button.updateButtonData = updateButtonData

	button:SetAttribute("showgrid", 0)
	button:SetAttribute("showstates", "")
	button:SetAttribute("hotkeys", "")
	button:SetAttribute("hasaction", true)
	button:SetAttribute("_childupdate", [[

			self:SetAttribute("stateshown", false)

			for showstate in gmatch(self:GetAttribute("showstates"), "[^;]+") do
				if (message and strfind(message, showstate)) then
					if (self:GetAttribute("hasaction") or self:GetAttribute("showgrid-bar") or self:GetAttribute("editmode")) then
						self:Show()
					end
					self:SetAttribute("stateshown", true)
				end
			end

			if (not self:GetAttribute("stateshown")) then
				self:Hide()
			end
		]] )

	if (not ss["menu"]) then
		ss["menu"] = {}
	end

	ss["menu"][index] = { button.config }

	Macaroon.MenuButtons[index] = { button, 1 }

	return button
end

local function updateVariables(element, defaultConfig)

	-- Add new vars
	for key,value in pairs(defaultConfig) do

		if (element.config[key] == nil) then

			if (element.config[lower(key)] ~= nil) then

				element.config[key] = element.config[lower(key)]
				element.config[lower(key)] = nil
			else
				element.config[key] = value
			end
		end
	end
	-- Add new vars

	-- Kill old vars
	for key,value in pairs(element.config) do
		if (defaultConfig[key] == nil) then
			element.config[key] = nil
		end
	end
	-- Kill old vars
end

local function bagbarUpdate(bar, state)

	if (not bar[state]) then return end

	if (bar[state].buttonCount == 1) then
		MacaroonBackpackButton:SetScript("OnClick", function() OpenAllBags() end)
	else
		MacaroonBackpackButton:SetScript("OnClick", function() if (IsModifiedClick()) then OpenAllBags() else ToggleBackpack() end end)
	end
end

function Macaroon.XtrasLoadSavedData(saved, profile)

	if (saved) then

		load = true

		local savedState = copyTable(saved)
		local newBar, defaultConfig = false

		if (savedState.bagbars) then

			clearTable(Macaroon.BagBars)

			defaultConfig = Macaroon.GetBarDefaults()

			for k,v in pairs(savedState.bagbars) do

				local bar = Macaroon.CreateBar("bag", true, true)

				bar.config = copyTable(savedState.bagbars[k][1])

				updateVariables(bar, defaultConfig)

				bar.handler:SetAttribute("state-current", bar.config.currentstate)

				bar.handler:SetAttribute("state-last", bar.config.laststate)

				bar.updateFunc = bagbarUpdate

				bar.reverse = true
			end

			savedState.bagbars = nil

		elseif (not profile) then

			newBar = Macaroon.CreateBar("bag", true, true)
		end

		if (savedState.bags) then

			for k,v in pairs(Macaroon.BagButtons) do
				Macaroon.StoreButton(v[1], Macaroon.BagButtons)
			end

			defaultConfig = Macaroon.GetXtrasButtonDefaults()

			for k,v in pairs(savedState.bags) do

				local button = createBagButton(k)

				button.config = copyTable(savedState.bags[k][1])

				--temp fix
				if (button.config.hotKeys) then
					button.config.hotKeys = gsub(button.config.hotKeys, "»", ":")
					button.config.hotKeyText = gsub(button.config.hotKeyText, "»", ":")
				end

				updateVariables(button, defaultConfig)
			end

			savedState.bags = nil

		elseif (not profile) then

			for k,v in ipairs(bagElements) do
				createBagButton(k)
			end
		end

		if (newBar) then
			Macaroon.AddButton(#bagElements, newBar)
		end

		if (newBar) then
			Macaroon.Ypos = Macaroon.UpdateBarPositions(Macaroon.BagBars, true, Macaroon.Ypos)
		end



		if (savedState.menubars) then

			clearTable(Macaroon.MenuBars)

			defaultConfig = Macaroon.GetBarDefaults()

			for k,v in pairs(savedState.menubars) do

				local bar = Macaroon.CreateBar("menu", true, true)

				bar.config = copyTable(savedState.menubars[k][1])

				updateVariables(bar, defaultConfig)

				bar.handler:SetAttribute("state-current", bar.config.currentstate)

				bar.handler:SetAttribute("state-last", bar.config.laststate)
			end

			savedState.menubars = nil

		elseif (not profile) then

			newBar = Macaroon.CreateBar("menu", true, true)
		end

		if (savedState.menu) then

			for k,v in pairs(Macaroon.MenuButtons) do
				Macaroon.StoreButton(v[1], Macaroon.MenuButtons)
			end

			defaultConfig = Macaroon.GetXtrasButtonDefaults()

			for k,v in pairs(savedState.menu) do

				local button = createMenuButton(k)

				button.config = copyTable(savedState.menu[k][1])

				--temp fix
				if (button.config.hotKeys) then
					button.config.hotKeys = gsub(button.config.hotKeys, "»", ":")
					button.config.hotKeyText = gsub(button.config.hotKeyText, "»", ":")
				end

				updateVariables(button, defaultConfig)
			end

			savedState.menu = nil

		elseif (not profile) then

			for k,v in ipairs(menuElements) do
				createMenuButton(k)
			end
		end

		if (newBar) then
			Macaroon.AddButton(#menuElements, newBar)
		end

		if (newBar) then
			Macaroon.Ypos = Macaroon.UpdateBarPositions(Macaroon.MenuBars, true, Macaroon.Ypos)
		end

		for k,v in pairs(savedState) do
			if (ss[k]) then
				ss[k] = v
			end
		end
	end
end

function Macaroon.XtrasUpdateElements()

	for k,v in pairs(Macaroon.BagBars) do

		v.stateschanged = true

		v.buttonCountChanged = true

		v.updateBar(v, true, true, true, true)
	end

	for k,v in pairs(Macaroon.BagBars) do

		v.updateBarLink(v)
	end

	for k,v in pairs(Macaroon.MenuBars) do

		v.stateschanged = true

		v.buttonCountChanged = true

		v.updateBar(v, true, true, true, true)
	end

	for k,v in pairs(Macaroon.MenuBars) do

		v.updateBarLink(v)
	end
end

function Macaroon.XtrasSaveCurrentState()

	if (load) then

		if (ss.bagbars) then
			clearTable(ss.bagbars)
		else
			ss.bagbars = {}
		end

		for k,v in pairs(Macaroon.BagBars) do
			ss.bagbars[k] = { v.config }
		end

		if (ss.bags) then
			clearTable(ss.bags)
		else
			ss.bags = {}
		end

		for k,v in pairs(Macaroon.BagButtons) do
			ss.bags[k] = { v[1].config }
		end

		if (ss.menubars) then
			clearTable(ss.menubars)
		else
			ss.menubars = {}
		end

		for k,v in pairs(Macaroon.MenuBars) do
			ss.menubars[k] = { v.config }
		end

		if (ss.menu) then
			clearTable(ss.menu)
		else
			ss.menu = {}
		end

		for k,v in pairs(Macaroon.MenuButtons) do
			ss.menu[k] = { v[1].config }
		end

		ss.savedVersion = currentVersion
	end

	return ss, "bagbars;menubars", "bags;menu"
end

function Macaroon.BagBarDefaults(bar)

	bar.config.name = "Bag Bar "..bar:GetID()
	bar.config.padH = 2.5

	bar.reverse = true
	bar.updateFunc = bagbarUpdate

	bar.handler:SetAttribute("state-current", bar.config.currentstate)
	bar.handler:SetAttribute("state-last", bar.config.laststate)
end

function Macaroon.MenuBarDefaults(bar)

	bar.config.name = "Menu Bar "..bar:GetID()
	bar.config.padH = 1

	bar.handler:SetAttribute("state-current", bar.config.currentstate)
	bar.handler:SetAttribute("state-last", bar.config.laststate)
end

function Macaroon.GetXtrasButtonDefaults()

	local defaults = {}

	buttonDefaults(0, defaults)

	return defaults.config
end

function Macaroon.AddXtrasButton(bar)
	-- do nothing
end

function containerFrame_OnShow(self)

	local index = abs(self:GetID()-5)

	if (bagElements[index]) then
		bagElements[index]:SetChecked(1)
	end
end

function containerFrame_OnHide(self)

	local index = abs(self:GetID()-5)

	if (bagElements[index]) then
		bagElements[index]:SetChecked(0)
	end
end

local function updateMicroButtons()

	if (MacaroonCharacterButton and CharacterFrame:IsShown()) then

		MacaroonCharacterButton:SetButtonState("PUSHED", 1)
		Macaroon.CharacterButton_SetPushed(MacaroonCharacterButton)

	elseif (MacaroonCharacterButton) then

		MacaroonCharacterButton:SetButtonState("NORMAL")
		Macaroon.CharacterButton_SetNormal(MacaroonCharacterButton)
	end

	if (MacaroonSpellbookButton and SpellBookFrame:IsShown()) then

		MacaroonSpellbookButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonSpellbookButton) then

		MacaroonSpellbookButton:SetButtonState("NORMAL")
	end

	if (MacaroonTalentButton and PlayerTalentFrame and PlayerTalentFrame:IsShown()) then

		MacaroonTalentButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonTalentButton) then

		MacaroonTalentButton:SetButtonState("NORMAL")
	end

	if (MacaroonQuestLogButton and QuestLogFrame:IsShown()) then

		MacaroonQuestLogButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonQuestLogButton) then

		MacaroonQuestLogButton:SetButtonState("NORMAL")
	end

	if (MacaroonLatencyButton and (GameMenuFrame:IsShown() or InterfaceOptionsFrame:IsShown() or (KeyBindingFrame and KeyBindingFrame:IsShown()) or (MacroFrame and MacroFrame:IsShown()))) then

		MacaroonLatencyButton:SetButtonState("PUSHED", 1)
		Macaroon.LatencyButton_SetPushed(MacaroonLatencyButton)

	elseif (MacaroonLatencyButton) then

		MacaroonLatencyButton:SetButtonState("NORMAL")
		Macaroon.LatencyButton_SetNormal(MacaroonLatencyButton)
	end

	if (MacaroonPVPButton and PVPFrame:IsShown()) then

		MacaroonPVPButton:SetButtonState("PUSHED", 1)
		Macaroon.PVPButton_SetPushed(MacaroonPVPButton)

	elseif (MacaroonPVPButton) then

		MacaroonPVPButton:SetButtonState("NORMAL")
		Macaroon.PVPButton_SetNormal(MacaroonPVPButton)
	end

	if (MacaroonSocialsButton and FriendsFrame:IsShown()) then

		MacaroonSocialsButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonSocialsButton) then

		MacaroonSocialsButton:SetButtonState("NORMAL")
	end

	if (MacaroonLFGButton and LFGParentFrame:IsShown())  then

		MacaroonLFGButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonLFGButton) then

		MacaroonLFGButton:SetButtonState("NORMAL")
	end

	if (MacaroonHelpButton and HelpFrame:IsShown()) then

		MacaroonHelpButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonHelpButton) then

		MacaroonHelpButton:SetButtonState("NORMAL")
	end

	if (MacaroonAchievementButton and AchievementFrame and AchievementFrame:IsShown() ) then

		MacaroonAchievementButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonAchievementButton) then

		MacaroonAchievementButton:SetButtonState("NORMAL")
	end

	if (MacaroonKeyRingButton and IsBagOpen(KEYRING_CONTAINER)) then

		MacaroonKeyRingButton:SetButtonState("PUSHED", 1)

	elseif (MacaroonKeyRingButton) then

		MacaroonKeyRingButton:SetButtonState("NORMAL")
	end
end

function Macaroon.CharacterButton_OnLoad(self)

	self.portrait = _G[self:GetName().."Portrait"]
	SetPortraitTexture(self.portrait, "player")

	self:SetNormalTexture("Interface\\Buttons\\UI-MicroButtonCharacter-Up")
	self:SetPushedTexture("Interface\\Buttons\\UI-MicroButtonCharacter-Down")
	self:SetHighlightTexture("Interface\\Buttons\\UI-Button-Hilight")
	self:RegisterEvent("UNIT_PORTRAIT_UPDATE")
	self:RegisterEvent("UPDATE_BINDINGS")
	self.tooltipText = MicroButtonTooltipText(CHARACTER_BUTTON, "TOGGLECHARACTER0")
	self.newbieText = NEWBIE_TOOLTIP_CHARACTER

	menuElements[#menuElements+1] = self
end

function Macaroon.CharacterButton_OnMouseDown(self)

	if ( self.down ) then
		self.down = nil
		ToggleCharacter("PaperDollFrame")
		return
	end
	Macaroon.CharacterButton_SetPushed(self)
	self.down = 1
end

function Macaroon.CharacterButton_OnMouseUp(self)

	if ( self.down ) then
		self.down = nil
		if (MouseIsOver(self)) then
			ToggleCharacter("PaperDollFrame")
		else
			updateMicroButtons()
		end
		return
	end
	if ( self:GetButtonState() == "NORMAL" ) then
		Macaroon.CharacterButton_SetPushed(self)
		self.down = 1
	else
		Macaroon.CharacterButton_SetNormal(self)
		self.down = 1
	end
end

function Macaroon.CharacterButton_OnEvent(self, event, ...)

	if (event == "UNIT_PORTRAIT_UPDATE") then

		if (... == "player") then
			SetPortraitTexture(self.portrait, ...)
		end

	elseif (event == "UPDATE_BINDINGS") then

		self.tooltipText = MicroButtonTooltipText(CHARACTER_BUTTON, "TOGGLECHARACTER0")
	end
end

function Macaroon.CharacterButton_SetPushed(self)
	self.portrait:SetTexCoord(0.2666, 0.8666, 0, 0.8333)
	self.portrait:SetAlpha(0.5)
end

function Macaroon.CharacterButton_SetNormal(self)
	self.portrait:SetTexCoord(0.2, 0.8, 0.0666, 0.9)
	self.portrait:SetAlpha(1.0)
end

function Macaroon.SpellbookButton_OnLoad(self)

	self:SetAttribute("type", "macro")
	self:SetAttribute("*macrotext*", "/click SpellbookMicroButton")

	LoadMicroButtonTextures(self, "Spellbook")
	menuElements[#menuElements+1] = self
end

function Macaroon.SpellbookButton_OnClick(self)
	if (not InCombatLockdown()) then
		ToggleSpellBook(BOOKTYPE_SPELL)
	end
end

function Macaroon.SpellbookButton_OnEnter(self)

	if (PlayerHasSpells()) then
		self.tooltipText = MicroButtonTooltipText(SPELLBOOK_ABILITIES_BUTTON, "TOGGLESPELLBOOK")
	else
		self.tooltipText = MicroButtonTooltipText(ABILITYBOOK_BUTTON, "TOGGLEABILITYBOOK")
	end

	GameTooltip_AddNewbieTip(self, self.tooltipText, 1.0, 1.0, 1.0, NEWBIE_TOOLTIP_SPELLBOOK)
end

function Macaroon.TalentButton_OnLoad(self)

	LoadMicroButtonTextures(self, "Talents")

	self.tooltipText = MicroButtonTooltipText(TALENTS_BUTTON, "TOGGLETALENTS")
	self.newbieText = NEWBIE_TOOLTIP_TALENTS
	self:RegisterEvent("PLAYER_LEVEL_UP")
	self:RegisterEvent("UPDATE_BINDINGS")
	self:RegisterEvent("UNIT_LEVEL")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")

	menuElements[#menuElements+1] = self
end

function Macaroon.TalentButton_OnClick(self)
	ToggleTalentFrame()
end

function Macaroon.TalentButton_OnEvent(self, event, ...)

	if (event == "PLAYER_LEVEL_UP") then

		UpdateTalentButton()

		if (not CharacterFrame:IsShown()) then
			SetButtonPulse(self, 60, 1)
		end

	elseif (event == "UNIT_LEVEL" or event == "PLAYER_ENTERING_WORLD") then

		UpdateTalentButton()

	elseif ( event == "UPDATE_BINDINGS" ) then

		self.tooltipText =  MicroButtonTooltipText(TALENTS_BUTTON, "TOGGLETALENTS")
	end
end

function Macaroon.AchievementButton_OnLoad(self)
	LoadMicroButtonTextures(self, "Achievement")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")

	menuElements[#menuElements+1] = self
end

function Macaroon.AchievementButton_OnEvent(self, event, ...)
	-- Put here to show/hide the achievement button
	AchievementMicroButton_Update()
end

function Macaroon.AchievementButton_OnClick(self)
	ToggleAchievementFrame()
end

function Macaroon.AchievementButton_OnEnter(self)
	self.tooltipText = MicroButtonTooltipText(ACHIEVEMENT_BUTTON, "TOGGLEACHIEVEMENT")
	GameTooltip_AddNewbieTip(self, self.tooltipText, 1.0, 1.0, 1.0, NEWBIE_TOOLTIP_ACHIEVEMENT)
end

function Macaroon.QuestLogButton_OnLoad(self)
	LoadMicroButtonTextures(self, "Quest")
	self.tooltipText = MicroButtonTooltipText(QUESTLOG_BUTTON, "TOGGLEQUESTLOG")
	self.newbieText = NEWBIE_TOOLTIP_QUESTLOG

	menuElements[#menuElements+1] = self
end

function Macaroon.QuestLogButton_OnEvent(self, event, ...)
	self.tooltipText = MicroButtonTooltipText(QUESTLOG_BUTTON, "TOGGLEQUESTLOG")
end

function Macaroon.QuestLogButton_OnClick(self)
	ToggleFrame(QuestLogFrame)
end

function Macaroon.SocialsButton_OnLoad(self)

	self:SetAttribute("type", "macro")
	self:SetAttribute("*macrotext*", "/click SocialsMicroButton")

	LoadMicroButtonTextures(self, "Socials")
	self.tooltipText = MicroButtonTooltipText(SOCIAL_BUTTON, "TOGGLESOCIAL")
	self.newbieText = NEWBIE_TOOLTIP_SOCIAL

	menuElements[#menuElements+1] = self
end

function Macaroon.SocialsButton_OnEvent(self, event, ...)
	self.tooltipText = MicroButtonTooltipText(SOCIAL_BUTTON, "TOGGLESOCIAL")
end

function Macaroon.PVPButton_OnLoad(self)

	self:RegisterEvent("UPDATE_BINDINGS")
	self:SetNormalTexture("Interface\\Buttons\\UI-MicroButtonCharacter-Up")
	self:SetPushedTexture("Interface\\Buttons\\UI-MicroButtonCharacter-Down")
	self:SetHighlightTexture("Interface\\Buttons\\UI-Button-Hilight")
	self.faction = _G[self:GetName().."Faction"]

	local factionGroup = UnitFactionGroup("player")

	if ( factionGroup ) then
		self.faction:SetTexture("Interface\\TargetingFrame\\UI-PVP-"..factionGroup)
	end

	self.tooltipText = MicroButtonTooltipText(PLAYER_V_PLAYER, "TOGGLEPVP")
	self.newbieText = NEWBIE_TOOLTIP_PVP

	menuElements[#menuElements+1] = self
end

function Macaroon.PVPButton_OnEvent(self, event, ...)
	self.tooltipText = MicroButtonTooltipText(PLAYER_V_PLAYER, "TOGGLEPVP")
	self.newbieText = NEWBIE_TOOLTIP_PVP
end

function Macaroon.PVPButton_OnMouseDown(self)

	if ( self.down ) then
		self.down = nil
		ToggleFrame(PVPFrame)
		return
	end

	Macaroon.PVPButton_SetPushed(self)
	self.down = 1
end

function Macaroon.PVPButton_OnMouseUp(self)

	if ( self.down ) then
		self.down = nil
		if ( MouseIsOver(self) ) then
			ToggleFrame(PVPFrame)
		else
			updateMicroButtons()
		end
		return
	end

	if ( self:GetButtonState() == "NORMAL" ) then
		Macaroon.PVPButton_SetPushed(self)
		self.down = 1
	else
		Macaroon.PVPButton_SetNormal(self)
		self.down = 1
	end
end

function Macaroon.PVPButton_SetPushed(self)
	self.faction:SetPoint("TOP", self, "TOP", 5, -31)
	self.faction:SetAlpha(0.5)
end

function Macaroon.PVPButton_SetNormal(self)
	self.faction:SetPoint("TOP", self, "TOP", 6, -30)
	self.faction:SetAlpha(1.0)
end

function Macaroon.LFGButton_OnLoad(self)
	LoadMicroButtonTextures(self, "LFG")
	self.tooltipText = MicroButtonTooltipText(LFG_BUTTON, "TOGGLELFGPARENT")
	self.newbieText = NEWBIE_TOOLTIP_LFGPARENT

	menuElements[#menuElements+1] = self
end

function Macaroon.LFGButton_OnEvent(self, event, ...)
	self.tooltipText = MicroButtonTooltipText(LFG_BUTTON, "TOGGLELFGPARENT")
	self.newbieText = NEWBIE_TOOLTIP_LFGPARENT
end

function Macaroon.LFGButton_OnClick(self)
	ToggleLFGParentFrame()
end

function Macaroon.HelpButton_OnLoad(self)
	LoadMicroButtonTextures(self, "Help")
	self.tooltipText = HELP_BUTTON
	self.newbieText = NEWBIE_TOOLTIP_HELP

	menuElements[#menuElements+1] = self
end

function Macaroon.HelpButton_OnClick(self)
	ToggleHelpFrame()
end

function Macaroon.LatencyButton_OnLoad(self)

	self.hover = nil
	self.elapsed = 0
	self.overlay = _G[self:GetName().."Overlay"]
	self.overlay:SetWidth(self:GetWidth()+1)
	self.overlay:SetHeight(self:GetHeight())
	self.tooltipText = MicroButtonTooltipText(MAINMENU_BUTTON, "TOGGLEGAMEMENU")
	self.newbieText = NEWBIE_TOOLTIP_MAINMENU
	self:RegisterForClicks("LeftButtonDown", "RightButtonDown", "LeftButtonUp", "RightButtonUp")
	self:RegisterEvent("PLAYER_LOGIN")
	self:RegisterEvent("UPDATE_BINDINGS")

	menuElements[#menuElements+1] = self

end

function Macaroon.LatencyButton_OnEvent(self, event, ...)

	if (event == "PLAYER_LOGIN") then
		self.lastStart = 0
		self.enabled = ss.scriptProfile
		GameMenuFrame:HookScript("OnShow", Macaroon.LatencyButton_SetPushed)
		GameMenuFrame:HookScript("OnHide", Macaroon.LatencyButton_SetNormal)
	end

	self.tooltipText = MicroButtonTooltipText(MAINMENU_BUTTON, "TOGGLEGAMEMENU")
end

function Macaroon.LatencyButton_OnClick(self, button, down)

	if (button == "RightButton") then

		if (IsShiftKeyDown()) then

			if (ss.scriptProfile) then

				SetCVar("scriptProfile", "0")
				ss.scriptProfile = false
			else

				SetCVar("scriptProfile", "1")
				ss.scriptProfile = true

			end

			ReloadUI()

		end

		if (not down) then

			if (self.alt_tooltip) then
				self.alt_tooltip = false
			else
				self.alt_tooltip = true
			end

			Macaroon.LatencyButton_SetNormal()
		else
			Macaroon.LatencyButton_SetPushed()
		end

		Macaroon.LatencyButton_OnEnter(self)

	elseif (IsShiftKeyDown()) then

		ReloadUI()

	else

		if ( self.down ) then
			self.down = nil;
			if ( not GameMenuFrame:IsShown() ) then
				CloseMenus()
				CloseAllWindows()
				PlaySound("igMainMenuOpen")
				ShowUIPanel(GameMenuFrame)
			else
				PlaySound("igMainMenuQuit")
				HideUIPanel(GameMenuFrame)
				Macaroon.LatencyButton_SetNormal()
			end
			if ( InterfaceOptionsFrame:IsShown() ) then
				InterfaceOptionsFrameCancel:Click()
			end
			return;
		end
		if ( self:GetButtonState() == "NORMAL" ) then
			Macaroon.LatencyButton_SetPushed()
			self.down = 1;
		else

			self.down = 1;
		end
	end
end

function Macaroon.LatencyButton_OnUpdate(self, elapsed)

	self.elapsed = self.elapsed + elapsed

	if (self.elapsed > 2.5) then

		local r, g, rgbValue
		local bandwidthIn, bandwidthOut, latency = GetNetStats()

		if (latency <= 1000) then
			rgbValue = math.floor((latency/1000)*100)
		else
			rgbValue = 100
		end

		if (rgbValue < 50) then
			r=rgbValue/50; g=1-(rgbValue/100)
		else
			r=1; g=abs((rgbValue/100)-1)
		end

		self.overlay:SetVertexColor(r, g, 0)

		if (self.hover) then
			Macaroon.LatencyButton_OnEnter(self)
		end

		if (self.enabled) then

			UpdateAddOnCPUUsage()
			UpdateAddOnMemoryUsage()

			self.lastUsage = self.currUsage or 0

			self.currUsage = GetScriptCPUUsage()

			self.usage = self.currUsage - self.lastUsage
		end

		self.elapsed = 0
	end

end

function Macaroon.LatencyButton_OnEnter(self)

	self.hover = 1

	if (self.alt_tooltip and not MacaroonXtrasTooltip.wasShown) then

		Macaroon.LatencyButton_AltOnEnter(self)
		MacaroonXtrasTooltip:AddLine("\nLatency Button by LedMirage of MirageUI")
		GameTooltip:Hide()
		MacaroonXtrasTooltip:Show()

	elseif (MouseIsOver(self)) then

		MainMenuBarPerformanceBarFrame_OnEnter(self)
		GameTooltip:AddLine("\nLatency Button by LedMirage of MirageUI")
		MacaroonXtrasTooltip:Hide()
		GameTooltip:Show()
	end
end

function Macaroon.LatencyButton_AltOnEnter(self)

	if (not MacaroonXtrasTooltip:IsVisible()) then
		MacaroonXtrasTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE")
	end

	if (self.enabled) then

		MacaroonXtrasTooltip:SetText("Script Profiling is |cff00ff00Enabled|r", 1, 1, 1)
		MacaroonXtrasTooltip:AddLine("(Shift-RightClick to Disable)", NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
		MacaroonXtrasTooltip:AddLine("\n|cfff00000Warning:|r Script Profiling Affects Game Performance\n", 1, 1, 1, 1)

		for i=1, GetNumAddOns() do

			local name,_,_,enabled = GetAddOnInfo(i)

			if (not addonData[i]) then
				addonData[i] = { name = name, enabled = enabled	}
			end

			local addon = addonData[i]

			addon.currMem = GetAddOnMemoryUsage(i)

			if (not addon.maxMem or addon.maxMem < addon.currMem) then
				addon.maxMem = addon.currMem
			end

			local currCPU = GetAddOnCPUUsage(i)

			if (addon.lastUsage) then

				addon.currCPU = (currCPU - addon.lastUsage)/2.5

				if (not addon.maxCPU or addon.maxCPU < addon.currCPU) then
					addon.maxCPU = addon.currCPU
				end
			else
				addon.currCPU = currCPU
			end

			if (self.usage > 0) then
				addon.percentCPU = addon.currCPU/self.usage * 100
			else
				addon.percentCPU = 0
			end

			addon.lastUsage = currCPU

			addon.avgCPU = currCPU / self.lastStart
		end

		if (self.usage) then
			MacaroonXtrasTooltip:AddLine("|cffffffff("..format("%.2f",(self.usage) / 2.5).."ms)|r Total Script CPU Time\n", NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
		end

		sortData = copyTable(addonData)

		sort(sortData, function (addonA, addonB) if (addonA.enabled and addonB.enabled) then return addonA.currCPU > addonB.currCPU end end)

		for i,v in ipairs(sortData) do

			if (sortData[i].enabled) then

				local addLine = ""

				if (sortData[i].currCPU) then
					addLine = addLine.."|cffffffff("..format("%.2f", sortData[i].currCPU).."ms/"..format("%.1f", sortData[i].percentCPU).."%)|r "
				end

				if (sortData[i].name) then
					addLine = addLine..sortData[i].name.." "
				end

				--if (sortData[i].maxCPU) then
				--	addLine = addLine..format("%.2f", sortData[i].maxCPU).."(mem) "
				--end

				MacaroonXtrasTooltip:AddLine(addLine, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
			end
		end

	else

		MacaroonXtrasTooltip:SetText("Script Profiling is |cfff00000Disabled|r", 1, 1, 1)
		MacaroonXtrasTooltip:AddLine("(Shift-RightClick to Enable)", NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
		MacaroonXtrasTooltip:AddLine("\n|cfff00000Warning:|r Script Profiling Affects Game Performance\n", 1, 1, 1, 1)
	end
end

function Macaroon.LatencyButton_OnLeave(self)

	if (GameTooltip:IsVisible()) then
		self.hover = nil
		GameTooltip:Hide()
	end
end

function Macaroon.LatencyButton_SetPushed()
	MacaroonLatencyButton:SetNormalTexture("Interface\\AddOns\\MacaroonXtras\\Images\\MirageUI_LatencyButton_FramePushed")
	MacaroonLatencyButtonOverlay:SetPoint("CENTER", MacaroonLatencyButton, "CENTER", -1, -2)
end

function Macaroon.LatencyButton_SetNormal()
	MacaroonLatencyButton:SetNormalTexture("Interface\\AddOns\\MacaroonXtras\\Images\\MirageUI_LatencyButton_Frame")
	MacaroonLatencyButtonOverlay:SetPoint("CENTER", MacaroonLatencyButton, "CENTER", 0, -0.5)
end

function Macaroon.KeyRingButton_OnLoad(self)

	self:SetID(KEYRING_CONTAINER)
	self:RegisterForClicks("LeftButtonUp", "RightButtonUp")

	menuElements[#menuElements+1] = self
end

function Macaroon.KeyRingButton_OnClick(self)

	if (CursorHasItem()) then
		PutKeyInKeyRing()
	else
		ToggleKeyRing()
	end
end

function Macaroon.KeyRingButton_OnReceiveDrag(self)
	if (CursorHasItem()) then
		PutKeyInKeyRing()
	end
end

function Macaroon.KeyRingButton_OnEnter(self)
	GameTooltip_AddNewbieTip(self, KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b, KEYRING)
end

function Macaroon.KeyRingButton_OnLeave(self)
	GameTooltip:Hide()
end

local function updateFreeSlots(self)

	local totalSlots, totalFree, freeSlots, bagFamily = 0, 0

	for i=BACKPACK_CONTAINER, NUM_BAG_SLOTS do

		freeSlots, bagFamily = GetContainerNumFreeSlots(i)

		if (bagFamily == 0) then

			totalSlots = totalSlots + GetContainerNumSlots(i)
			totalFree = totalFree + freeSlots
		end
	end

	local rgbValue, r, g = math.floor((totalFree/MacaroonSavedState.freeSlots)*100)

	if (rgbValue > 49) then
		r=(1-(rgbValue/100))+(1-(rgbValue/100))
		g=(rgbValue/100)+((1-(rgbValue/100))/2)
	else
		r=1; g=(rgbValue/100)*1.5
	end

	self.freeSlots = totalFree

	self.count:SetText(format("%s", totalFree))
	self.count:SetTextColor(r, g, 0)
end

function Macaroon.MacaroonBackpackButton_OnLoad(self)

	self:RegisterForClicks("LeftButtonUp", "RightButtonUp")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")
	self:RegisterEvent("CVAR_UPDATE")
	self:RegisterEvent("BAG_UPDATE")

	self.count = _G[self:GetName().."Count2"]

	MacaroonBackpackButtonIconTexture:SetTexture([[Interface\Buttons\Button-Backpack-Up]])
end

function Macaroon.MacaroonBackpackButton_OnReceiveDrag(self, button)

	if ( not PutItemInBackpack() ) then
		ToggleBackpack()
	end

	local isVisible

	for i=1, NUM_CONTAINER_FRAMES, 1 do
		local frame = _G["ContainerFrame"..i]

		if (frame:GetID()==0 and frame:IsShown()) then
			isVisible = 1; break
		end
	end

	self:SetChecked(isVisible)
end

function Macaroon.MacaroonBackpackButton_OnEnter(self)

	GameTooltip:SetOwner(self, "ANCHOR_LEFT")
	GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)

	local keyBinding = GetBindingKey("TOGGLEBACKPACK")

	if ( keyBinding ) then
		GameTooltip:AppendText(" "..NORMAL_FONT_COLOR_CODE.."("..keyBinding..")"..FONT_COLOR_CODE_CLOSE)
	end

	GameTooltip:AddLine(format(NUM_FREE_SLOTS, (self.freeSlots or 0)))

	GameTooltip:Show()
end

function Macaroon.MacaroonBackpackButton_OnLeave(self)
	GameTooltip:Hide()
end

function Macaroon.MacaroonBackpackButton_OnEvent(self, event, ...)

	if ( event == "BAG_UPDATE" ) then

		if ( ... >= BACKPACK_CONTAINER and ... <= NUM_BAG_SLOTS ) then
			updateFreeSlots(self)
		end

	elseif ( event == "PLAYER_ENTERING_WORLD" ) then

		if ( GetCVar("displayFreeBagSlots") == "1" ) then
			self.count:Show()
			MacaroonMainMenuSlider4:Enable()
			MacaroonMainMenuSlider4.text2:SetTextColor(1.0, 0.82, 0)
		else
			self.count:Hide()
			MacaroonMainMenuSlider4:Disable()
			MacaroonMainMenuSlider4.text2:SetTextColor(0.5,0.5,0.5)
		end

		updateFreeSlots(self)

	elseif ( event == "CVAR_UPDATE" ) then

		if ( select(1,...) == "DISPLAY_FREE_BAG_SLOTS" ) then

			if ( select(2,...) == "1" ) then
				self.count:Show()
				MacaroonMainMenuSlider4:Enable()
				MacaroonMainMenuSlider4.text2:SetTextColor(1.0, 0.82, 0)
			else
				self.count:Hide()
				MacaroonMainMenuSlider4:Disable()
				MacaroonMainMenuSlider4.text2:SetTextColor(0.5,0.5,0.5)
			end
		end
	end
end

function Macaroon.XtrasSetSaved()

	if (MacaroonSavedState.useShared and MacaroonSharedSavedState[MacaroonSavedState.sharedProfile]) then
		ss = MacaroonSharedSavedState[MacaroonSavedState.sharedProfile]

		if (not ss) then
			ss = MacaroonXtrasSavedState
		end
	else
		ss = MacaroonXtrasSavedState
	end

	return ss
end

local function controlOnEvent(self, event, ...)

	if (event == "VARIABLES_LOADED") then

		Macaroon.XtrasSetSaved()

		bagElements[5] = MacaroonBackpackButton
		bagElements[4] = Macaroon_Bag0Slot
		bagElements[3] = Macaroon_Bag1Slot
		bagElements[2] = Macaroon_Bag2Slot
		bagElements[1] = Macaroon_Bag3Slot

		for k,v in pairs(bagElements) do
			v:SetWidth(32)
			v:SetHeight(32)
			v:GetNormalTexture():SetWidth(55)
			v:GetNormalTexture():SetHeight(55)
			v:GetNormalTexture():SetPoint("CENTER",0,0)
			_G[v:GetName().."IconTexture"]:ClearAllPoints()
			_G[v:GetName().."IconTexture"]:SetPoint("TOPLEFT", -1, 1)
			_G[v:GetName().."IconTexture"]:SetPoint("BOTTOMRIGHT")
		end

		hooksecurefunc("UpdateMicroButtons", updateMicroButtons)
		hooksecurefunc("ContainerFrame_OnShow", containerFrame_OnShow)
		hooksecurefunc("ContainerFrame_OnHide", containerFrame_OnHide)

		Macaroon.CreateBarTypes.bag = { "Bagbars", ss, Macaroon.BagBars, Macaroon.BagButtons, "MacaroonBagButton", Macaroon.AddXtrasButton, Macaroon.BagBarDefaults, "4Bag Bar" }
		Macaroon.CreateBarTypes.menu = { "Menubars", ss, Macaroon.MenuBars, Macaroon.MenuButtons, "MacaroonMenuButton", Macaroon.AddXtrasButton, Macaroon.MenuBarDefaults, "5Menu Bar" }

		Macaroon.StatesToSave.xtras = Macaroon.XtrasSaveCurrentState
		Macaroon.SavedDataLoad.xtras = Macaroon.XtrasLoadSavedData
		Macaroon.SavedDataUpdate.xtras = Macaroon.XtrasUpdateElements
		Macaroon.SetSavedVars.xtras = Macaroon.XtrasSetSaved

	elseif (event == "PLAYER_LOGIN") then

		Macaroon.XtrasLoadSavedData(ss)

	elseif (event == "PLAYER_ENTERING_WORLD" and not playerEnteredWorld) then

		Macaroon.XtrasUpdateElements()

		playerEnteredWorld = true

	end
end

local frame = CreateFrame("Frame", nil, UIParent)
frame:SetScript("OnEvent", controlOnEvent)
frame:RegisterEvent("VARIABLES_LOADED")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("BAG_UPDATE")